home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
progjrn
/
pj_5_6.arc
/
SHELLASM.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-09-15
|
46KB
|
915 lines
;Copyright 1987, John J. Newlin
PUBLIC setxy,upcase,cga_retrace,fillstr,screenwrite,init_screen,savebox
PUBLIC restbox,shiftl,shiftr,hi,lo,move,chdir,findfirst,findnext,cls
PUBLIC strng,video_mode,set_mem,getdir,msdos,set_dta,scroll,keycode
PUBLIC exec,hide_cursor,rest_cursor,save_cursor,longstr,addlong
toolcode segment word PUBLIC 'code'
assume cs:toolcode
;;;;;;;;;;;;;;
;changes lower case char to upper case
;function upcase(ch : char) : char
upcase proc near
push bp
mov bp,sp ;save BP
mov ax,[bp+4] ;get the char
cmp al,97 ;is it 'a' or above?
jb u_exit ;no, do nothing
cmp al,122 ;is it 'z' or below?
ja u_exit ;no, do nothing
sub al,32 ;change to upper case
u_exit: mov [bp+6],ax ;return as function result
pop bp
ret 2
upcase endp
;;;;;;;;;;;;;;;
;uses undocumented interrupt 2E to execute a program
;procedure exec(var name : string);
exec proc near
push bp ;save bp
mov bp,sp ;bp points to the stack
push ax ;save
push bx ; all
push cx ; other
push dx ; regs
push di
push si
jmp past ;jump over storage area
mls_ds dw 0 ;stores our DS reg
mls_es dw 0 ;stores our ES reg
mls_ss dw 0 ;stores our SS reg
mls_sp dw 0 ;stores our SP reg
mls_bp dw 0 ;stores our BP reg
past:
mov cs:mls_ss,ss ;save SS reg
mov cs:mls_sp,sp ;save SP reg
mov cs:mls_es,es ;save ES reg
mov cs:mls_ds,ds ;save DS reg
mov cs:mls_bp,bp ;save BP reg
push ds
pop es ;set ES = DS
mov si,[bp+4] ;si points to command string
int 2Eh ;call DOS to execute
mov ax,cs:mls_ss ;retrieve SS reg
mov ss,ax ;reset it
mov sp,cs:mls_sp ;retrieve SP reg
mov ax,cs:mls_ds ;retrieve DS reg
mov ds,ax ;reset it
mov ax,cs:mls_es ;retrieve ES reg
mov es,ax ;reset it
mov bp,cs:mls_bp ;retrieve BP reg
pop si ;restore
pop di ; all
pop dx ; other
pop cx ; regs
pop bx
pop ax
pop bp
ret 2
exec endp
;;;;;;;;;;;;
;returns keyboard status byte, ascii code, and scan code
;function keycode(var status,ascii,scan : integer) : boolean;
keycode proc near
push bp
mov bp,sp ;BP points to stack
push bx ;Marshal says save BX
push si ;and also SI
mov ah,1 ;Int 16h to check buffer
int 16h ;call BIOS
mov word ptr [bp+10],0 ;function returns a false
jz _no_key ;no key avail, so depart
mov ah,0 ;key is avail, so get it
int 16h ;call BIOS
push ax ;save result
mov ah,2 ;to get status byte
int 16h ;call BIOS
mov bx,[bp+8] ;get address of status
mov ah,0 ;zero the MSB
mov [bx],ax ;set status
pop ax ;restore AX
mov bx,[bp+6] ;get address of ascii
mov si,[bp+4] ;get address of scan
xor dx,dx ;zero DX
mov dl,ah ;put scan value in DX
mov [si],dx ;move it into scan
mov dl,al ;move ascii code into DL
mov [bx],dx ;and into ascii
mov word ptr[bp+10],1 ;function returns true
_no_key: pop si
pop bx
pop bp
ret 6
keycode endp
;;;;;;;;;;;;;;;
;scrolls the specified area of the screen up/down number of lines
;normalize to screen dimensions of (1,1) to (25,80)
;procedure scroll(ulx,uly,lrx,lry,lines,attr,dir : integer); external;
scroll proc near
push bp
mov bp,sp ;BP points to stack
push bx ;must preserve BX
mov bh,byte ptr 6[bp] ;get desired attribute
mov ch,byte ptr 14[bp] ;upper left y coord
dec ch ;normalize
mov cl,byte ptr 16[bp] ;upper left x coord
dec cl ;normalize
mov dh,byte ptr 10[bp] ;lower right y coord
dec dh ;normalize
mov dl,byte ptr 12[bp] ;lower right x coord
dec dl ;normalize
mov al,byte ptr 08[bp] ;no. of lines to scroll
cmp byte ptr 4[bp],0 ;scroll up?
je scroll_up ;yes
mov ah,7 ;no, scroll down
jmp short scroll_it ;do it
scroll_up: mov ah,6 ;scroll up
scroll_it: int 10h ;call BIOS
pop bx
pop bp
ret 14
scroll endp
;;;;;;;;;;;;;
;set the Disk Transfer Area to desired structure
;procedure set_dta(var buffer : buff_type);
set_dta proc near
push bp
mov bp,sp ;BP points to stack
mov dx,[bp+4] ;get address of buffer
mov ah,1Ah ;function to set DTA
int 21h ;DOS will do it
pop bp
ret 2
set_dta endp
;;;;;;;;;;;;;;
;call DOS interrupt 21h with registers set as desired
;procedure msdos(var regs : regtype)
msdos proc near
push bp
mov bp,sp ;BP points to stack
push ax ;save
push bx ; all
push cx ; regs
push dx ;
push di ;
push si ;
push ds ;
push es ;
jmp short pst ;leap over code seg data
saveit dw 0
pst:
mov bx,[bp+4] ;BX points to regs structure
mov ax,[bx+0] ;set AX
mov cx,[bx+4] ;set CX
mov dx,[bx+6] ;set DX
mov di,[bx+8] ;set DI
mov si,[bx+10] ;set SI
mov cs:saveit,ds ;save our DS reg
push [bx+14] ;push ES value in structure
pop es ;pop it into ES
push [bx+2] ;push BX value in structure
push [bx+12] ;push DS value in structure
pop ds ;set DS
pop bx ;set BX
push bp ;save our BP during call
int 21h ;call DOS
pop bp ;restore our BP
push ds ;save returned DS
push bx ;save returned BX
mov bx,cs:saveit ;get our DS reg
mov ds,bx ;set our DS
mov bx,[bp+4] ;get pointer to structure
pop [bx+2] ;set structure BX
pop [bx+12] ;set structure DS
mov [bx+0],ax ;set structure AX
mov [bx+4],cx ;set structure CX
mov [bx+6],dx ;set structure DX
mov [bx+8],di ;set structure DI
mov [bx+10],si ;set structure SI
push es ;push returned ES
pop [bx+14] ;pop it into structure ES
pushf ;push returned flags
pop [bx+16] ;pop into structure flags
pop es ;restore
pop ds ; all
pop si ; regs
pop di ;
pop dx ;
pop cx ;
pop bx ;
pop ax ;
pop bp ;
ret 2
msdos endp
;;;;;;;;;;;;;
;returns active drive and directory in string
;drive code 0 = A, 1 = B, etc.
;procedure getdir(var dirname : string);
getdir proc near
push bp
mov bp,sp ;BP points to stack
push si ;must preserve SI
mov si,[bp+4] ;SI points to dirname
mov ah,19h ;set up to get drive desig
int 21h ;call DOS
add al,65 ;make it a char
mov byte ptr[si],al ;put in string
inc si ;point to next char
mov al,58 ;58 = ':'
mov byte ptr[si],al ;put in string
inc si ;point to next char
mov byte ptr[si],'\' ;put in backslash
inc si ;point to next char
mov ah,47h ;set up to get default dir
int 21h ;call DOS
pop si
pop bp
ret 2
getdir endp
;;;;;;;;;;;;;;
;set program memory to only what is required by code, data, and stack
;function set_mem : integer;
set_mem proc near
push bp ;save BP
mov bp,sp ;BP points to stack
push es ;save ES
push bx ;save BX
mov ax,ds ;AX = DS
mov bx,cs ;BX = CS
sub ax,bx ;ds-cs = data seg paragraphs
inc ax ;round up one
mov bx,ax ;store in BX
mov ax,bp ;AX = stack pointer
mov cl,4 ;for shifting
shr ax,cl ;convert to paragraphs
add ax,bx ;add BX
add ax,32 ;bump by 32 paragraph overhead
mov bx,ax ;store in BX
mov cx,ax ;save in CX
mov ax,cs ;AX = code segment
sub ax,16 ;AX set to mem control block seg
mov es,ax ;ES = mem control block seg
mov ah,4Ah ;DOS mod alloc mem function
int 21h ;DOS will do it
jnc no_mem_err ;error will set carry flag
mov cx,-1 ;if error return -1
no_mem_err: mov [bp+4],cx ;function result
pop bx ;restore BX
pop es ;restore ES
pop bp ;restore BP
ret
set_mem endp
;;;;;;;;;;;;;;;
;converts an integer into a Pascal string
;procedure strng(num : integer; var numstr : string)
strng proc near
push bp
mov bp,sp ;BP points to stack
push bx ;preserve BX
push di ;preserve DI
push es ;preserve ES
push ds ;preserve DS
mov ax,ds ;get DS
mov es,ax ;make ES = DS
mov di,[bp+4] ;DI points to string
mov dx,[bp+6] ;AX = integer to convert
xor bx,bx ;zero BX
new_char: mov ax,dx
xor dx,dx ;zero DX
mov cx,10 ;for decimal conversion
div cx ;AX gets result
xchg ax,dx ;swap AX and DX
add al,30h ;convert to ascii
push ax ;save AX
inc bx ;bump count
cmp dx,0 ;are we done?
jnz new_char ;no, get another digit
str_loop:
pop ax ;restore AX
stosb ;put in string
dec bx ;dec count
cmp bx,0 ;are we done?
jne str_loop ;no, do again
mov al,0 ;AL = 0
stosb ;end of string byte
pop ds ;restore
pop es ; regs
pop di ;
pop bx ;
pop bp ;
ret 4
strng endp
;;;;;;;;;;;
;clears the entire screen using the specified attribute
;procedure cls(attr : integer);
cls proc near
push bp
mov bp,sp ;BP points to stack
push bx ;preserve BX
mov ah,7 ;code to scroll
mov al,0 ;AL = 0 so all will be blanked
mov bh,byte ptr[bp+4] ;attribute for scroll
mov cx,0 ;CL = 0, CH = 0
mov dx,184Fh ;DL = 79, DH = 24
int 10h ;call BIOS
pop bx ;restore BX
pop bp
ret 2
cls endp
;;;;;;;;;;;;;;;;;
;returns current video mode
;function vide_mode : integer
video_mode proc near
push bp
mov bp,sp ;BP points to stack
mov ah,0Fh ;set up to get mode
int 10h ;call BIOS
mov ah,0 ;clear upper half
mov 4[bp],ax ;return function result
pop bp
ret
video_mode endp
;;;;;;;;;;;;;;;;;;
;if file is found, returns a 0 - returns non-zero otherwise
;function findfirst(var pathname : string; attr : integer) : integer
findfirst proc near
push bp
mov bp,sp ;BP points to stack
mov dx,[bp+6] ;DX points to ASCIIZ string
mov cx,[bp+4] ;CX = file attribute
mov ah,4Eh ;set up to find first
int 21h ;call DOS
jc ff_err ;carry flag set if not found
mov ax,0 ;was found, so AX = 0
ff_err: mov [bp+8],ax ;return function result
pop bp
ret 4
findfirst endp
;;;;;;;;;;;;;;;;;;
;returns 0 if next find is successful, non-zero if not
;function findnext : integer
findnext proc near
push bp
mov bp,sp ;BP points to stack
mov ah,4Fh ;set up for find next
int 21h ;call DOS
jc fn_err ;carry flag set if not found
mov ax,0 ;was found, so AX = 0
fn_err: mov [bp+4],ax ;return function result
pop bp
ret
findnext endp
;;;;;;;;;;;;;;;;;;;;;;;
;changes to specified drive/directory
;returns 0 if successful, non-zero if not
;function chdir(var dirname : string) : integer;
chdir proc near
push bp
mov bp,sp ;BP points to stack
push si ;must preserve SI
mov si,[bp+4] ;SI points to dirname
cmp byte ptr [si+1],':' ;is drive spec present
jne no_drive ;if not, skip drive stuff
mov dl,[si] ;yes, get drive letter
cmp dl,65 ;is it below 'A'
jb no_drive ;yes, skip
cmp dl,90 ;is it above 'Z'
ja lo_case_desig ;yes, check lower case
sub dl,65 ;convert letter to byte
jmp drv_ok ;continue
lo_case_desig: cmp dl,97 ;is it below 'a'
jb no_drive ;yes, skip
cmp dl,122 ;is it above 'z'
ja no_drive ;yes, skip
sub dl,97 ;convert letter to byte
drv_ok: mov ah,0Eh ;change drive
int 21h ;call DOS
cmp byte ptr [si+2],0 ;are we done?
je are_done ;yes
no_drive: mov dx,si ;dx points to directory
mov ah,3Bh ;set up to change
int 21h ;call DOS
jc ch_err ;if err don't zero AX
are_done: mov ax,0 ;AX = 0
ch_err: mov [bp+6],ax ;return function result
pop si ;restore SI
pop bp
ret 2
chdir endp
;;;;;;;;;;;;;;;
;returns most significant byte of num
;function hi(num : integer) : integer;
hi proc near
push bp
mov bp,sp ;BP points to stack
mov ax,[bp+4] ;AX = num
xchg ah,al ;swap
mov ah,0 ;clear upper half
mov [bp+6],ax ;return function result
pop bp
ret 2
hi endp
;;;;;;;;;;;;;;;;;
;returns least significant byte of num
;functio lo(num : integer) : integer;
lo proc near
push bp
mov bp,sp ;BP points to stack
mov ax,[bp+4] ;AX = num
mov ah,0 ;clear upper half
mov [bp+6],ax ;return function result
pop bp
ret 2
lo endp
;;;;;;;;;;;;;;;;;
;shifts target to the left by quantity bits
;function shiftl(target,bits : integer) : integer;
shiftl proc near
push bp
mov bp,sp ;BP points to stack
mov cl,byte ptr [bp+4] ;CL = bits
mov ax,[bp+6] ;AX = target
shl ax,cl ;shift left
mov [bp+8],ax ;return function result
pop bp
ret 4
shiftl endp
;;;;;;;;;;;;;;;;;
;shifts target to the right by quantity bits
;function shiftr(target,bits : integer) : integer;
shiftr proc near
push bp
mov bp,sp ;BP points to stack
mov cl,byte ptr [bp+4] ;CL = bits
mov ax,[bp+6] ;AX = target
shr ax,cl ;shift right
mov [bp+8],ax ;return function result
pop bp
ret 4
shiftr endp
;;;;;;;;;;;;;;;;;;
;initializes video ram address and video type variables
;procedure init_screen;
init_screen proc near
push bp
jmp short past_data
vid_addr dw 0B000h
mono_box db 1
past_data: push ds ;save DS
push bx ;save BX
mov ah,0Fh ;set up to get mode
int 10h ;call BIOS
cmp al,7 ;is it mono?
je mc ;yes
mov ax,0B800h ;no, set up for CGA
mov cl,0 ;for mono_box
jmp short continue ;and continue
mc: mov ax,0B000h ;set up for mono
mov cl,1 ;for mono_box
continue: mov cs:vid_addr,ax ;save video address
mov cs:mono_box,cl ;save the flag
pop bx ;restore BX
pop ds ;restore DS
pop bp
ret
init_screen endp
;;;;;;;;;;;;;;;;;;;
;waits for horiz and vertical retrace before writing to video ram
cga_retrace proc near
retrace: in al,dx ;get status
test al,8 ;check retrace
jnz horiz ;ok - chech horiz
rcr al,1 ;check retrace
jc retrace ;check again
horiz: in al,dx ;get status
rcr al,1 ;check retrace
jnc horiz ;test again
store_it: ret
cga_retrace endp
;;;;;;;;;;;;;;;;;;
;saves the video area defined by row,col, width and depth to buff
;procedure savebox(col,row,width,depth,buff);
savebox proc near
push bp
mov bp,sp ;BP points to stack
push ds ;save
push es ; important
push bx ; regs
push di ; on
push si ; stack
push ss
pop es ;ES = SS
jmp short mc2 ;jump over data and proc
s_width dw 0
s_offset dw 0
mc2: mov ax,cs:vid_addr ;get video address
continue2: mov ds,ax ;put in DS
mov di,[bp+4] ;DI points to buffer
mov ax,[bp+10] ;AX = row
dec ax ;normalize
mov bx,160 ;160 bytes per row
mul bx ;times number of rows
mov si,ax ;SI points to video start
mov bx,[bp+12] ;BX = col
dec bx ;normalize
shl bx,1 ;times 2
mov dx,[bp+8] ;DX = width
shl dx,1 ;times 2
mov cs:s_width,dx ;save width
mov cs:s_offset,160 ;save offset
sub cs:s_offset,dx ;subtract width
add si,bx ;add to SI
mov cx,[bp+6] ;CX = depth
cmp cs:vid_addr,0B000h ;mono screen?
mov ax,8[bp] ;AX = width
je mono9 ;yes, go to mono routine
again9: push cx ;save CX = depth
mov cx,[bp+8] ;CX = width
mov dx,03DAh ;CGA port
loop9: cli ;halt interrupts
call cga_retrace ;wait for CGA retrace
store9: movsw ;store the char and attribute
sti ;restore interrupts
loop loop9 ;do again
pop cx ;restore CX = depth
add si,cs:s_offset ;add the offset
loop again9 ;and continue
jmp y_done ;until done
mono9: push cx ;save CX = depth
mov cx,ax ;CX = AX = width
rep movsw ;do it
add si,cs:s_offset ;add the offset
pop cx ;restore CX = depth
loop mono9 ;do again
y_done: pop si ;restore
pop di ; regs
pop bx ; from
pop es ; the
pop ds ; stack
pop bp
ret 10
savebox endp
;;;;;;;;;;;;;;;;;;;;
;restores buffer to video area defined by col, row, width, and depth
;procedure restbox(col,row,width,depth,buff : integer)
restbox proc near
push bp
mov bp,sp ;BP points to stack
push ds ;save
push es ; important
push bx ; regs
push di ; on
push si ; stack
mov ax,cs:vid_addr ;AX = video address
mov es,ax ;ES = video address
mov si,[bp+4] ;SI points to buff
mov ax,[bp+10] ;AX = row
dec ax ;normalize
mov bx,160 ;160 bytes per row
mul bx ;times number of rows
mov di,ax ;DI points to area
mov bx,[bp+12] ;BX = col
dec bx ;normalize
shl bx,1 ;times 2
mov dx,[bp+8] ;DX = width
shl dx,1 ;times 2
mov cs:s_width,dx ;store width
mov cs:s_offset,160 ;store offset
sub cs:s_offset,dx ;DX = offset
add di,bx ;DI points to area
mov cx,[bp+6] ;CX = depth
cmp cs:mono_box,1 ;mono screen?
mov ax,[bp+8] ;AX = video segment
je mono6 ;go to mono routine
again6: push cx ;save CX = depth
mov cx,[bp+8] ;CX = width
mov dx,03DAh ;CGA port address
loop6: cli ;turn off interrupts
call cga_retrace ;wait for retrace
store6: movsw ;store char and attribute
sti ;interrupts enabled
loop loop6 ;do again
pop cx ;CX = depth
add di,cs:s_offset ;add offset to DI
loop again6 ;and do another row
jmp x_done ;done with CGA
mono6: push cx ;save CX = depth
mov cx,ax ;CX = width
rep movsw ;move all at once
add di,cs:s_offset ;add offset to DI
pop cx ;CX = depth
loop mono6 ;do another row
x_done: pop si ;restore
pop di ; regs
pop bx ; from
pop es ; the
pop ds ; stack
pop bp
ret 10
restbox endp
;;;;;;;;;;;;;;;;;;;;;;;
;writes a string directly to video ram
; procedure screenwrite(col,row,attr:integer; var str : string);
screenwrite proc near
push bp
mov bp,sp ;BP points to stack
push es ;save
push bx ; regs
push di ; on
push si ; stack
mov ax,[bp+8] ;AX = row
dec ax ;normalize
mov bx,160 ;160 bytes per row
mul bx ;AX = AX * 160
mov di,ax ;DI points to video area
mov bx,[bp+10] ;BX = col
dec bx ;normalize
shl bx,1 ;adjust for attr byte
add di,bx ;DI = DI + col
mov si,[bp+4] ;SI points to string
mov ah,[bp+6] ;AH = attribute
mov dx,cs:vid_addr ;DX = video segment
cmp byte ptr cs:mono_box,1 ;mono screen?
mov es,dx ;ES = video segment
je sw_mono ;yes, go to mono routine
mov dx,03dah ;CGA port address
sw_getnext: lodsb ;AL = char
cmp al,0 ;end of string?
je sw_exit ;yes, exit
mov cx,ax ;no, save AX in CX
cli ;disable interrupts
call cga_retrace ;wait for retrace
sw_store: mov ax,cx ;restore AX
stosw ;store word in video ram
sti ;enable interrupts
jmp sw_getnext ;get next character
sw_mono: lodsb ;AL = next char
cmp al,0 ;end of string?
je sw_exit ;yes, exit
stosw ;no, store in video ram
jmp sw_mono ;get next character
sw_exit: pop si ;restore
pop di ; regs
pop bx ; from
pop es ; stack
pop bp
ret 8
screenwrite endp
;;;;;;;;;;;;;;;;;;;;;
;moves bytes from v1addr to v2addr
;procedure move(v1addr,v2addr,bytes : integer);
move proc near
push bp
mov bp,sp ;BP points to stack
push es ;save
push di ; regs
push si ; on stack
mov ax,ds ;AX = DS
mov es,ax ;ES = AX = DS
mov si,[bp+8] ;SI points to v1addr
mov di,[bp+6] ;DI points to v2addr
mov cx,[bp+4] ;CX number of bytes to move
rep movsb ;mass move
pop si ;restore
pop di ; regs
pop es ; from stack
pop bp
ret 6
move endp
;;;;;;;;;;;;;;;;;;;;;
;positions cursor to col, row values
;procedure setxy(col,row : integer)
setxy proc near
push bp
mov bp,sp ;BP points to stack
push bx ;preserve BX
mov bh,0 ;page is 0
mov ah,2 ;for BIOS call to move cursor
mov dh,[bp+4] ;DH = row
dec dh ;normalize
mov dl,[bp+6] ;DL = col
dec dl ;normalize
int 10h ;BIOS will move it
pop bx ;restore BX
pop bp
ret 4
setxy endp
;;;;;;;;;;;;;;;;;;;;;
;fills designated string with specified character
;procedure fillstr(var target : string; num,ch : integer);
fillstr proc near
push bp
mov bp,sp ;BP points to stack
push es ;save ES
mov ax,ds ;AX = DS
mov es,ax ;ES = AX = DS
mov di,8[bp] ;DI points to target string
mov cx,6[bp] ;CX = num
cmp cx,80 ;longer than 80 char?
jg poof ;yes, depart
mov al,byte ptr 4[bp] ;AL = ch
cld ;for forward move
rep stosb ;store ch in string
mov al,0 ;AL = 0
stosb ;for end of string byte
poof: pop es ;restore ES
pop bp
ret 6
fillstr endp
;;;;;;;;;;;;;;;;;;;;;
;adds two long integers - return result in total
;procedure addlong(var total,n1,n2 : longint)
addlong proc near
push bp
mov bp,sp
push bx ;save
push di ; regs
push si ; on stack
mov si,[bp+6] ;SI points to n1 low word
mov di,[bp+4] ;DI points to n2 low word
mov bx,[bp+8] ;BX points to total low word
mov cx,2 ;CX = 2
clc ;clear carry
add_em: mov ax,[si] ;AX = n1
inc si ;bump SI
inc si ;SI now points to n1 hi word
adc ax,[di] ;add n1 to n2
inc di ;bump di
inc di ;DI now points to n2 hi word
mov [bx],ax ;store in total lo word
inc bx ;bump bx
inc bx ;BX now points total hi word
loop add_em ;do again for hi word
pop si ;restore
pop di ; regs
pop bx ; from stack
pop bp
ret 6
addlong endp
;;;;;;;;;;;;;;;;;;;;
;converts a long integer into a string;
;procedure longstr( var long : longint; var str : longstr)
longstr proc near
push bp
mov bp,sp ;BP points to stack
push ds ;save
push es ; regs
push bx ; on
push si ; the
push di ; stack
jmp over_dat ;skip over data
temp_buff db 5 dup(0)
lstr db 12 dup(0)
over_dat: cld ;set direction to forward
mov ax,ds ;AX = DS
push ax ;save AX, we need DS later
mov bx,[bp+6] ;BX points to long low word
mov dx,[bx+2] ;DX points to long hi word
mov bx,[bx] ;BX = long low word
mov ax,cs ;AX = CS
mov ds,ax ;DS = AX = CS
mov es,ax ;ES = AX = CS
lea di,temp_buff ;DI points to buffer
mov cx,5 ;CX = 5 (for 10 digits)
mov al,0 ;AL = 0
clear: stosb ;store a 0
loop clear ;fill buffer with zeros
mov cx,32 ;
test dx,8000h ;is low word negative?
jz no_neg ;no, skip code
not dx ;DX = -DX
not bx ;BX = -BX
add bx,1 ;BX = BX + 1
adc dx,0 ;adjust for carry
no_neg: std ;set direction to back
l_loop: push cx ;save counter
mov cx,5 ;five bytes=10 digits
lea si,temp_buff ;SI points to buffer
add si,4 ;SI points to buffer end
mov di,si ;DI = SI
shl bx,1 ;grab a bit
rcl dx,1 ;and then rotate
adjust: lodsb ;load AL with byte
adc al,al ;add carry
daa ;decimal adjust
stosb ;store in temp_buff
loop adjust ;keep going
pop cx ;restore counter
loop l_loop ;and do again
cld ;set flag to forward
lea di,lstr ;DI points to lstr
xor dx,dx ;DX = 0
lea si,temp_buff ;SI points to buffer
mov cx,10 ;CX = 10 characters
xor bx,bx ;BX = 0
x_str: test cx,1 ;high or low?
jnz y_str ;low
lodsb ;AL = char
mov ah,al ;AH = AL
push cx ;save CX
mov cl,4 ;CL = 4
shr al,cl ;shift AL right 4
pop cx ;restore CX
jmp z_str ;do a character
y_str: mov al,ah ;low part
and al,0Fh ;and it
z_str: test al,0Fh ;is it zero?
jnz w_str ;no
or bx,bx ;a leading zero
jz l_next ;no
w_str: inc bx ;BX has length
or al,'0' ;AL = ASCII char
stosb ;store in string
l_next: loop x_str ;continue
add bx,dx ;add 0
jnz l_done ;are we done?
inc bx ;bump length
mov al,'0' ;make 0
stosb ;store it
l_done: cld ;back to forward
mov byte ptr [di],0 ;end of string byte
pop ax ;restore AX
mov es,ax ;ES = DS
lea si,lstr ;SI points to lstr
mov di,[bp+4] ;DI points to str
mov cx,12 ;we'll move all
rep movsb ;move them
pop di ;restore
pop si ; regs
pop bx ; from
pop es ; the
pop ds ; stack
pop bp
ret 4
longstr endp
;;;;;;;;;;;;;;;
;hides the cursor
hide_cursor proc near
mov ah,1 ;cursor size function
mov ch,20h ;set it to 20h
int 10h ;BIOS does it
ret
hide_cursor endp
;;;;;;;;;;;;;;;
;saves the DOS cursor for later restoration
save_cursor proc near
jmp get_it ;jump past data
save_curs dw 0
get_it: mov ah,3 ;get cursor size function
mov bh,0 ;page is 0
int 10h ;BIOS does it
mov cs:save_curs,cx ;CX has size - save it
ret
save_cursor endp
;;;;;;;;;;;;;;;
;restores the saved DOS cursor
rest_cursor proc near
mov cx,cs:save_curs ;retrieve cursor size
mov ah,1 ;set cursor size function
int 10h ;BIOS does it
ret
rest_cursor endp
toolcode ends
end